package com.kfm.base.compare;

import java.util.Arrays;
import java.util.Comparator;

/**
 * 对象之间的比较, 通过实现Comparable接口, 重写compareTo方法
 *
 * Comparable接口表示自然比较。 特点:
 *  1. 实现Comparable接口的类, 可以比较大小
 *  2. 实现Comparable接口的类, 可以进行自然排序
 *      自然排序: 从小到大排序
 *      自定义排序: 按照自定义的规则排序
 *  3. 实现Comparable接口的类, 要重写compareTo方法
 *     compareTo 自然比较方法 方法表示比较规则，参数是Object类型, 返回值是 int 类型。
 *     返回值是int类型, 有三种情况: 正数, 0, 负数 。
 *
 *  Comparator接口表示比较器。 特点:
 *  1. 实现Comparator接口的类, 可以比较两个对象的大小
 *  2. 实现Comparator接口的类, 可以进行自定义排序
 *      重写compare方法, 比较两个对象的大小
 *      返回值是int类型, 有三种情况: 正数, 0, 负数 。
 */
public class Demo {

    public static void main(String[] args) {
        String[] arr = {"cbd", "abc", "bca", "cba", "bac", "cab", "ab"};

        Student[] stus = {
                new Student("张三", 23, 90),
                new Student("李四", 25, 80),
                new Student("王五", 23, 70),
                new Student("赵六", 24, 80),
                new Student("田七", 25, 50)
        };

//        sort(arr);
//        sort(stus);
//        Comparator c = new StudentComparator();
//        int n = Objects.compare(stus[0], stus[1], c);
        // c.compare(stus[0], stus[1]);
//        System.out.println(n);

        // Arrays.sort 对对象数组进行排序时，对象必须实现 Comparable 接口
//        Arrays.sort(stus);

        Person[] p = {
                new Person("张三", 23),
                new Person("李四", 25),
                new Person("王五", 23),
                new Person("赵六", 24),
                new Person("田七", 25)
        };

//       Arrays.sort(stus, new Comparator<Student>() {
//           @Override
//           public int compare(Student o1, Student o2) {
//               // 只比较年龄
//               if (o1.getAge() > o2.getAge()){
//                   return 1;
//               } else if (o1.getAge() < o2.getAge()){
//                   return -1;
//               } else {
//                   return 0;
//               }
//           }
//       });

        // Lambda 表达式
        Arrays.sort(stus, (o1, o2) -> {
            // 只比较年龄
            if (o1.getAge() > o2.getAge()){
                return 1;
            } else if (o1.getAge() < o2.getAge()){
                return -1;
            } else {
                return 0;
            }

        });

//        Student stu = new Student("张三", 23, 90);

//        search(stu);
//        search(new Student("张三", 23, 90));



        // 遍历
        for (Student stu : stus) {
            System.out.println(stu);
        }
    }

    private static void sort(Student[] stus) {
        // 冒泡
        for (int i = 0; i < stus.length - 1; i++) {
            // 每次比较的次数
            for (int j = 0; j < stus.length - 1 - i; j++) {
                // 比较
                if (stus[j].compareTo(stus[j + 1]) > 0) {
                    // 交换
                    Student temp = stus[j];
                    stus[j] = stus[j + 1];
                    stus[j + 1] = temp;
                }
            }
        }
    }

    private static void sort(String[] arr) {
        // 冒泡
        for (int i = 0; i < arr.length - 1; i++) {
            // 每次比较的次数
            for (int j = 0; j < arr.length - 1 - i; j++) {
                // 比较
                if (arr[j].compareTo(arr[j + 1]) > 0) {
                    // 交换
                    String temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

class Student implements Comparable, Cloneable {
    private String name;
    private int age;
    private int score;

    public Student() {
        super();
    }

    public Student(String name, int age, int score) {
        super();
        this.name = name;
        this.age = age;
        this.score = score;
    }

    /**
     * 比较 Student 对象的大小
     * 当前对象 和 o 比较
     * @param o the object to be compared.
     * @return 0: 相等, 正数: 当前对象 大于 o, 负数: 当前对象 小于 o
     *
     * 重写：方法名相同，参数列表相同，返回值相同，访问修饰符相同或变大，抛出异常相同或变小
     */
    @Override
    public int compareTo(Object o) throws RuntimeException {
        // 1. 判断 o 是否是 Student 类型
        if (o instanceof Student student) {
            // 2. 比较 权重
            // 比较年龄
            if (this.age > student.age) {
                return 1;
            } else if (this.age < student.age) {
                return -1;
            }
            // 比较成绩
            if (this.score > student.score) {
                return 1;
            } else if (this.score < student.score) {
                return -1;
            }
            // 比较名字
            return this.name.compareTo(student.name);
        }
        /**
         *  checked exception 检查异常，必须处理
         *      Exception 异常
         *  unchecked exception 非检查异常，可以处理，也可以不处理
         *      RuntimeException 运行时异常
         *      Error 错误
         *
         *  编译时异常: 代码编译时, 就会报错 javac
          */
        throw new CompareException("类型不匹配");
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

/**
 * 自定义异常，继承现有的异常类
 */
class CompareException extends RuntimeException {
    public CompareException() {
        super();
    }

    public CompareException(String message) {
        super(message);
    }
}

class StudentComparator implements Comparator {

    /**
     * 比较两个 Student 对象的大小
     * @param o1 the first object to be compared.
     * @param o2 the second object to be compared.
     * @return
     */
    @Override
    public int compare(Object o1, Object o2) {
        if (o1 instanceof Student student && o2 instanceof  Student student1){
            // 比较 权重
            // 比较年龄
            if (student.getAge() > student1.getAge()) {
                return 1;
            } else if (student.getAge() < student1.getAge()) {
                return -1;
            }
            // 比较成绩
            if (student.getScore() > student1.getScore()) {
                return 1;
            } else if (student.getScore() < student1.getScore()) {
                return -1;
            }
            // 比较名字
            return student.getName().compareTo(student1.getName());
        }
        throw new CompareException("类型不匹配");
    }
}

class Person {
    private String name;
    private int age;

    public Person() {
        super();
    }

    public Person(String name) {
        super();
        this.name = name;
    }

    public Person(int age) {
        super();
        this.age = age;
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}
